1. /* slmhhmul.cpp by K.Tsuru */
  2. // function ID = 218 DRADIX, BRADIX
  3. /**************************************************************************
  4. SLong and SInteger classes
  5. result = (huge m)*(huge n) m >= n
  6. Normal method using distribution law.
  7. Using the FFT multiplication in which f*f=2f figures can be treated at the
  8. maximum it provides the product with over f figures.
  9. [Algorithm]
  10. m.FFTSize() == m.FFTMaxArraySize();
  11. It lets f = m.FFTMaxArraySize()/2 and takes F = R^f as the new radix, where
  12. R=DRADIX or BRADIX.
  13. mf, nf:the number of figures(blocks) in radix F.
  14. m and n can be expressed as follows
  15. m = u(mf-1)*F^(mf-1)+u(mf-2)*F^(mf-2)+...+u(0)
  16. n = v(mf-1)*F^(nf-1)+v(nf-2)*F^(nf-2)+...+v(0)
  17. Calculating u(i)*v(j) by FFT it is put in the (i+j)-th block of r.
  18. When &m == &n(result = m*m) the calculation u(i)*v(j)(i > j) needs once.
  19. **************************************************************************/
  20. #ifndef SN_H
  21. #include "sn.h"
  22. #endif
  23. void SLong::NHHMult(const SLong& m, const SLong& n, SLong& result){
  24. uint f = m.FFTSize()/2, d, k;
  25. int i, j, mf, nf;
  26. bool m_sq = (&m == &n); // m == n, result = m*m ?
  27. //figures of m = m.aHead + 1
  28. mf = (m.aHead+1)/f; if( (m.aHead+1) % f ) mf++;
  29. nf = (n.aHead+1)/f; if( (n.aHead+1) % f ) nf++;
  30. /*
  31. mf <= maxArraySize/f = 8
  32. The "m.Size()" is a multiple of "f" because the "size" is a the power of two.
  33. m >= n then maybe n.Size()<f.
  34. If n.Size() <= f it directly use the value of "n" as "q".
  35. */
  36. uint qsz = (n.Size() <= f) ? 0 : f;
  37. if( (&result == &m) || (&result == &n)){
  38. m.SetError(m.SYNTAX_ERR, "NHHMult", 218);
  39. }
  40. result.valloc(m.aHead+n.aHead+2, 0); //It allocates memory and initialize.
  41. //worc area, The size of "t" is the same as that of "result". p = q = t = 0
  42. SLong p(m.Type(), f), q(m.Type(), qsz), t(m.Type(), result.Size());
  43. const fType* mv = m.ReadFigures();
  44. const fType* nv = n.ReadFigures();
  45. fType* pv = p.figure.Elements();
  46. fType* qv = NULL;
  47. if(qsz) qv = q.figure.Elements();
  48. #ifndef NDEBUG
  49. m.figure(mf*f-1u);
  50. #endif
  51. for(i = 0; i < mf; i++){
  52. p.SetSign(1);
  53. //It copys f figures to p down from the upper part of m.
  54. d = i*f;
  55. if(d > m.aHead) continue; // p = 0
  56. for(k = d ; k < d+f; k++) pv[k - d] = mv[k];
  57. p.CheckArray(218); //It lets to know the LLMultFFT() the figure positions.
  58. if( !p.Sign(218) ) continue;
  59. for(j = 0; j < nf; j++){
  60. if(m_sq && (i < j)) continue;
  61. if(qsz){ // n.Size() > f
  62. d = j*f;
  63. if(d > n.aHead) continue; // q = 0
  64. if( m_sq && (i == j) ){
  65. t = LLMult(p, p);
  66. } else {
  67. q.SetSign(1);
  68. for(k = d ; k < d+f; k++) qv[k - d] = nv[k];
  69. q.CheckArray(218);
  70. if(q.Sign(218) == 0) continue;
  71. t = LLMult(p, q);
  72. }
  73. } else {// nf = 1, n.Size() <= f, q = n
  74. t = LLMult(p, n);
  75. }
  76. if(m_sq && (i > j)) t = LsMult(t, 2); // if i == j, t = p*p
  77. if(i+j) t.ShiftArray( (i+j)*f ); // t *= F^(i+j)
  78. result = LLAdd(result, t); // result += t;
  79. }
  80. }
  81. //A surplus of one figure was taken.It is a rare case.
  82. if( 2u*(result.aHead+1) <= result.figure.size() ) result.DoCutDown();
  83. }

slmhhmul.cpp : last modifiled at 2017/03/13 14:32:00(3,142 bytes)
created at 2017/10/07 10:26:49
The creation time of this html file is 2017/11/09 14:52:03 (Thu Nov 09 14:52:03 2017).